
#include "DecodeThread.h"
#include <QDebug>
#include <QElapsedTimer>

// FFmpeg 头文件
extern "C" {
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/pixfmt.h>  // AVPixelFormat
}


DecodeThread::DecodeThread(QObject* parent)
    : QThread(parent)
    , m_decoder(new VideoDecoder())
    , m_swsCtx(nullptr)
    , m_currentPixelFormat(AV_PIX_FMT_NONE)  // 初始化为无效格式
    , m_audioDecoder(new AudioDecoder())
    , m_audioOutput(new AudioOutput(this))
    , m_hasAudio(false)
    , m_isPlaying(false)
    , m_stopRequested(false)
    , m_seekRequested(false)
    , m_seekPositionMs(0)
    , m_frameDelay(0)
    , m_playbackSpeed(1.0)  // 默认正常速度
{
    qDebug() << "[DecodeThread] 创建解码线程";
}

DecodeThread::~DecodeThread()
{
    stop();
    wait();

    freeSwsContext();
    delete m_decoder;
    
    // 清理音频资源
    if (m_audioOutput) {
        m_audioOutput->stop();
        delete m_audioOutput;
    }
    if (m_audioDecoder) {
        m_audioDecoder->closeAudio();
        delete m_audioDecoder;
    }

    qDebug() << "[DecodeThread] 销毁解码线程";
}


bool DecodeThread::openVideo(const QString& videoPath)
{
    QMutexLocker locker(&m_mutex);

    // 先关闭旧文件，避免 FFmpeg 资源冲突
    if (m_decoder->isOpened()) {
        m_decoder->closeVideo();
        freeSwsContext();
    }
    
    // 关闭旧音频
    if (m_hasAudio) {
        m_audioDecoder->closeAudio();
        m_hasAudio = false;
    }
    
    // 重置状态
    m_stopRequested = false;
    m_seekRequested = false;

    // 先打开视频
    if(!m_decoder->openVideo(videoPath))
    {
        emit errorOccurred(m_decoder->getError());
        return false;
    }

    //初始化图像转换器（使用默认格式，实际格式会在第一帧解码时动态调整）
    int width=m_decoder->getVideoWidth();
    int height=m_decoder->getVideoHeight();
    if(!initSwsContext(width, height, AV_PIX_FMT_YUV420P))
    {
        m_decoder->closeVideo();
        emit errorOccurred(QString("无法初始化图像转换器: %1x%2").arg(width).arg(height));
        return false;
    }

    //计算延迟
    double fps=m_decoder->getFps();

    if(fps>0)
    {
    m_frameDelay = static_cast<int>(1000.0 / fps);  // 毫秒
    } 
    else {
    m_frameDelay = 33;  // 默认 30fps
    }

    emit durationChanged(m_decoder->getVideoDurationMs());
    qDebug() << "[DecodeThread] 视频打开成功，帧延迟：" << m_frameDelay << "ms";
    
    // 尝试打开音频流
    m_hasAudio = false;
    if (m_audioDecoder->openAudio(videoPath)) {
        qDebug() << "[DecodeThread] 音频流打开成功";
        
        // 初始化音频输出
        if (m_audioOutput->init(m_audioDecoder->getSampleRate(), 
                                 m_audioDecoder->getChannels(),
                                 m_audioDecoder->getSwrContext())) {
            m_hasAudio = true;
            qDebug() << "[DecodeThread] 音频输出初始化成功";
        } else {
            qDebug() << "[DecodeThread] 警告：音频输出初始化失败";
            m_audioDecoder->closeAudio();
        }
    } else {
        qDebug() << "[DecodeThread] 警告：无音频流或打开失败：" << m_audioDecoder->getError();
    }
    
    return true;
}


//关闭视频

void DecodeThread::closeVideo()
{
    stop();
    wait();
    QMutexLocker locker(&m_mutex);
    m_decoder->closeVideo();
    freeSwsContext();
    
    // 关闭音频
    if (m_hasAudio) {
        m_audioOutput->stop();
        m_audioOutput->clearBuffer();
        m_audioDecoder->closeAudio();
        m_hasAudio = false;
        qDebug() << "[DecodeThread] 音频关闭";
    }
    
    m_isPlaying=false;
    m_stopRequested=false;
    m_seekRequested=false;
    m_seekPositionMs=0;
    m_frameDelay=0;
    qDebug() << "[DecodeThread] 视频关闭";
}

void DecodeThread::play()
{
    if(!m_decoder->isOpened())
    {
        qDebug() << "[DecodeThread] 无法播放，视频未打开";
        return;
    }

    m_isPlaying=true;
    m_stopRequested=false;
    if(!isRunning())
    {
        start();
    }
    
    // 开始播放音频
    if (m_hasAudio) {
        m_audioOutput->play();
    }

    m_condition.wakeAll();//唤醒线程
    qDebug() << "[DecodeThread] 视频播放";
}

void DecodeThread::pause()
{
    bool hasAudio = false;
    
    // 先在锁内设置暂停标志
    {
        QMutexLocker locker(&m_mutex);
        m_isPlaying = false;
        hasAudio = m_hasAudio;
        qDebug() << "[DecodeThread] 设置暂停标志";
    }
    // ← 释放 m_mutex 后再操作音频，避免嵌套锁死锁
    
    // 暂停音频（在锁外执行，避免死锁）
    if (hasAudio && m_audioOutput) {
        m_audioOutput->pause();
        qDebug() << "[DecodeThread] 音频已暂停";
    }
}

void DecodeThread::stop()
{
    bool hasAudio = false;
    
    // 先在锁内设置停止标志
    {
        QMutexLocker locker(&m_mutex);
        m_stopRequested = true;
        m_isPlaying = false;
        hasAudio = m_hasAudio;
    }
    // ← 释放 m_mutex
    
    // 唤醒可能在等待的解码线程（在锁外调用）
    m_condition.wakeAll();
    
    // 停止音频（在锁外执行，避免死锁）
    if (hasAudio && m_audioOutput) {
        m_audioOutput->stop();  // stop() 内部已经调用了 clearBuffer()
    }
    
    qDebug() << "[DecodeThread] 停止播放";
}

void DecodeThread::seek(int64_t positionMs)
{
    QMutexLocker locker(&m_mutex);
    m_seekRequested = true;
    m_seekPositionMs = positionMs;
    m_condition.wakeOne();
    qDebug() << "[DecodeThread] 请求跳转到：" << positionMs << "ms";
}

int64_t DecodeThread::getDurationMs() const
{
    return m_decoder->getVideoDurationMs();
}

void DecodeThread::setVolume(int volume)
{
    if (m_hasAudio && m_audioOutput) {
        m_audioOutput->setVolume(volume);
        qDebug() << "[DecodeThread] 设置音量：" << volume;
    }
}

void DecodeThread::setPlaybackSpeed(double speed)
{
    QMutexLocker locker(&m_mutex);
    
    // 限制倍速范围在 0.25x ~ 4.0x（视频）
    if (speed < 0.25) speed = 0.25;
    if (speed > 4.0) speed = 4.0;
    
    m_playbackSpeed = speed;
    qDebug() << "[DecodeThread] 设置视频播放速度：" << speed << "x";
    
    // 同时设置音频倍速
    if (m_hasAudio && m_audioDecoder && m_audioOutput) {
        double audioSpeed = qBound(0.25, speed, 4.0);
        
        qDebug() << "[DecodeThread] 准备调整音频倍速：" << audioSpeed << "x";
        
        // 记录当前播放状态
        bool wasPlaying = m_isPlaying;
        
        // 1. 停止音频播放（以便重新初始化 SDL2）
        qDebug() << "[DecodeThread] 停止音频播放...";
        m_audioOutput->stop();
        
        // 2. 调整音频倍速（重新初始化重采样器，调整输出采样率）
        locker.unlock();
        bool success = m_audioDecoder->setSpeed(audioSpeed);
        locker.relock();
        
        if (!success) {
            qDebug() << "[DecodeThread] ❌ 音频倍速调整失败";
            if (wasPlaying) {
                m_audioOutput->play();
            }
            return;
        }
        
        // 3. 🎯 关键：重新初始化 AudioOutput，使用新的采样率
        qDebug() << "[DecodeThread] 重新初始化音频输出（新采样率）...";
        // 正确公式：2倍速需要更高采样率（88200），0.5倍速需要更低采样率（22050）
        int newSampleRate = static_cast<int>(m_audioDecoder->getSampleRate() * audioSpeed);
        
        locker.unlock();
        bool initSuccess = m_audioOutput->init(newSampleRate, 
                                               m_audioDecoder->getChannels(),
                                               m_audioDecoder->getSwrContext());
        locker.relock();
        
        if (!initSuccess) {
            qDebug() << "[DecodeThread] ❌ 音频输出重新初始化失败！";
            return;
        }
        
        qDebug() << "[DecodeThread] ✅ 音频倍速调整成功：" << audioSpeed << "x（简单倍速，会变调）";
        qDebug() << "[DecodeThread]   重采样器输出：" << newSampleRate << "Hz";
        qDebug() << "[DecodeThread]   SDL2 播放：" << newSampleRate << "Hz";
        
        if (audioSpeed > 1.5) {
            qDebug() << "[DecodeThread]   ⚠️ 声音会变快 + 音调变高（花栗鼠效果）";
        } else if (audioSpeed < 0.75) {
            qDebug() << "[DecodeThread]   ⚠️ 声音会变慢 + 音调变低";
        }
        
        // 4. 设置 AudioOutput 的倍速（用于时间计算修正）
        m_audioOutput->setPlaybackSpeed(audioSpeed);
        
        // 5. 如果之前在播放，恢复播放
        if (wasPlaying) {
            qDebug() << "[DecodeThread] 恢复音频播放...";
            m_audioOutput->play();
        }
        
        if (qAbs(audioSpeed - speed) > 0.01) {
            qDebug() << "[DecodeThread] 注意：音频倍速被限制为" << audioSpeed << "x（原请求：" << speed << "x）";
        }
    }
}

void DecodeThread::run()
{
    QElapsedTimer timer;
    bool videoEof = false;
    bool audioEof = false;

    while(true)
    {
        m_mutex.lock();
        if(m_stopRequested)
        {
            m_mutex.unlock();
            break;
        }

        //检查是否跳转

        if(m_seekRequested)
        {
            m_seekRequested=false;
            int64_t seekPos=m_seekPositionMs;
            bool wasPlaying = m_isPlaying;
            m_mutex.unlock();

            qDebug() << "[DecodeThread] 开始 seek 到：" << seekPos << "ms";
            
            // 跳转视频
            m_decoder->seek(seekPos);
            qDebug() << "[DecodeThread] 视频 seek 完成";
            
            // 同时跳转音频
            if (m_hasAudio) {
                qDebug() << "[DecodeThread] 开始音频 seek，wasPlaying =" << wasPlaying;
                
                // 先暂停音频播放，避免死锁
                qDebug() << "[DecodeThread] 调用 pause...";
                m_audioOutput->pause();
                qDebug() << "[DecodeThread] pause 完成";
                
                // 清空缓冲区
                qDebug() << "[DecodeThread] 调用 clearBuffer...";
                m_audioOutput->clearBuffer();
                qDebug() << "[DecodeThread] clearBuffer 完成";
                
                // 跳转音频解码器
                qDebug() << "[DecodeThread] 音频解码器 seek...";
                m_audioDecoder->seek(seekPos);
                qDebug() << "[DecodeThread] 音频解码器 seek 完成";
                
                // 如果之前在播放，恢复播放
                if (wasPlaying) {
                    qDebug() << "[DecodeThread] 调用 play...";
                    m_audioOutput->play();
                    qDebug() << "[DecodeThread] play 完成";
                }
            }
            
            emit positionChanged(seekPos);
            videoEof = false;
            audioEof = false;
            qDebug() << "[DecodeThread] seek 完全完成";
            m_mutex.lock();
        }

        //检查是否暂停

        if(!m_isPlaying)
        {
            m_condition.wait(&m_mutex);
            m_mutex.unlock();
            continue;
        }
        m_mutex.unlock();

        // ========== 音频解码 ==========
        // 保持音频缓冲区有数据（但不要太满）
        if (m_hasAudio && !audioEof && !m_stopRequested) {  // 🔧 先检查停止标志
            int audioBufferSize = m_audioOutput->getBufferSize();
            if (audioBufferSize < 5 && !m_stopRequested) {  // 🔧 再次检查
                // qDebug() << "[DecodeThread] 音频缓冲区不足，当前：" << audioBufferSize << "，开始解码";
                
                int decodeCount = 0;
                while (m_audioOutput->getBufferSize() < 5 && !audioEof && decodeCount < 10 && !m_stopRequested) {  // 检查停止标志
                    bool isAudioEof = false;
                    AudioFrame audioFrame = m_audioDecoder->decodeFrame(isAudioEof);
                    
                    if (audioFrame.isValid()) {
                        m_audioOutput->pushFrame(std::move(audioFrame));
                        decodeCount++;
                    } else if (isAudioEof) {
                        audioEof = true;
                        qDebug() << "[DecodeThread] 音频解码完成";
                        break;
                    } else {
                        // 解码失败，跳出循环避免死循环
                        qDebug() << "[DecodeThread] 音频解码失败，跳出";
                        break;
                    }
                }
            }
        }
        
        // ========== 视频解码 ==========
        //开始计时
        timer.start();
        //解码一帧视频
        bool isVideoEof=false;

        VideoFrame frame=m_decoder->decodeFrame(isVideoEof);

        if(frame.isValid())
        {
            //转化为QImage
            QImage image=convertToQImage(frame);

            if(!image.isNull())
            {
                // ========== 音视频同步逻辑 ==========
                if (m_hasAudio && m_isPlaying) {
                    // 获取当前音频播放时间（毫秒，已考虑倍速）
                    int64_t audioTimeMs = m_audioOutput->getCurrentTimeMs();
                    
                    // 获取视频帧的 PTS（毫秒）
                    int64_t videoTimeMs = frame.getPtsMs();
                    
                    // 计算差值：正数表示视频快了，负数表示视频慢了
                    int64_t diff = videoTimeMs - audioTimeMs;
                    
                    // qDebug() << "[Sync] 音频:" << audioTimeMs << "ms, 视频:" << videoTimeMs << "ms, 差值:" << diff << "ms";
                    
                    // 同步策略
                    if (diff > 100) {
                        // 视频快了超过100ms，延迟显示
                        int sleepTime = qMin((int)diff, 500);  // 最多延迟500ms
                        // qDebug() << "[Sync] 视频快了" << diff << "ms，延迟" << sleepTime << "ms";
                        msleep(sleepTime);
                    } else if (diff < -100) {
                        // 视频慢了超过100ms，跳帧（不显示这一帧）
                        // qDebug() << "[Sync] 视频慢了" << diff << "ms，跳帧";
                        // 不发送 frameDecoded，直接continue到下一帧
                    } else {
                        // 差值在合理范围内（-100ms ~ +100ms），正常显示
                        emit frameDecoded(image, videoTimeMs);
                        emit positionChanged(videoTimeMs);
                        
                        // 控制播放速度（使用帧率作为基准，应用倍速）
                        int elapsed = timer.elapsed();
                        int adjustedDelay = static_cast<int>(m_frameDelay / m_playbackSpeed);
                        int sleeptime = adjustedDelay - elapsed;
                        if(sleeptime > 0) {
                            msleep(sleeptime);
                        }
                    }
                } else {
                    // 没有音频，使用原来的帧率控制（应用倍速）
                    emit frameDecoded(image,frame.getPtsMs());
                    emit positionChanged(frame.getPtsMs());
                    
                    int elapsed=timer.elapsed();
                    int adjustedDelay = static_cast<int>(m_frameDelay / m_playbackSpeed);
                    int sleeptime=adjustedDelay-elapsed;
                    if(sleeptime>0)
                    {
                        msleep(sleeptime);
                    }
                }
            }
        }else if(isVideoEof)
        {
            videoEof = true;
            
            // 如果视频和音频都结束了，才算播放完成
            if (!m_hasAudio || audioEof) {
                qDebug() << "[DecodeThread] 播放结束";
                emit playbackFinished();
                
                QMutexLocker locker(&m_mutex);
                m_isPlaying = false;
            } else {
                // 视频结束了，但音频还在播放，稍微等待
                msleep(10);
            }
        }
        
    }
    
    qDebug() << "[DecodeThread] 线程退出";
}

bool DecodeThread::initSwsContext(int width, int height, int pixelFormat)
{
    freeSwsContext();

    //创建新的转换器
    m_swsCtx = sws_getContext(
        width, height, (AVPixelFormat)pixelFormat,  // 源格式（动态传入）
        width, height, AV_PIX_FMT_RGB24,             // 目标格式（RGB24）
        SWS_BILINEAR,                                // 缩放算法
        nullptr, nullptr, nullptr
    );

    if(!m_swsCtx)
    {
        qDebug() << "[DecodeThread] 无法创建图像转换器";
        return false;
    }
    
    m_currentPixelFormat = pixelFormat;  // 记录当前格式
    qDebug() << "[DecodeThread] 图像转换器初始化成功，源格式：" << pixelFormat;
    return true;
}

void DecodeThread::freeSwsContext()
{
    if (m_swsCtx) {
        sws_freeContext(m_swsCtx);
        m_swsCtx = nullptr;
    }
    
}

QImage DecodeThread::convertToQImage(const VideoFrame& frame)
{
    if(!frame.isValid())
    {
        return QImage();
    }
    
    int width = frame.getWidth();
    int height = frame.getHeight();
    int pixelFormat = frame.getPixelFormat();

    // 检查像素格式是否改变，如果改变则重新初始化转换器
    if (!m_swsCtx || pixelFormat != m_currentPixelFormat) {
        qDebug() << "[DecodeThread] 像素格式改变，重新初始化转换器：" << pixelFormat;
        if (!initSwsContext(width, height, pixelFormat)) {
            qDebug() << "[DecodeThread] 重新初始化转换器失败";
            return QImage();
        }
    }

    //创建RGB图像
    QImage image(width, height, QImage::Format_RGB888);

    //准备目标数据
    uint8_t* dstData[1] = {image.bits()};
    int dstLinesize[1] = {static_cast<int>(image.bytesPerLine())};

    // 执行转换（任意格式 → RGB）
    sws_scale(
        m_swsCtx,
        frame.getData(),           // 源数据
        frame.getLinesize(),       // 源行跨度
        0,                         // 源起始行
        height,                    // 源高度
        dstData,                   // 目标数据（RGB）
        dstLinesize                // 目标行跨度
    );
    
    return image;
}